<!-- 
 * @description 跑马灯组件 - 支持水平和垂直方向的文字滚动效果
 * @property {String} direction 滚动方向 - 可选值：left/right/up/down
 * @property {Number} speed 滚动速度，默认60
 * @property {Number} delay 开始滚动的延迟时间，默认0
 * @property {String/Number} height 容器高度，默认80
 * @property {Boolean} autoplay 是否自动播放，默认true
 * @property {String/Number} gap 内容间隔，默认0
 * @example 
 *  <wht-race-lamp direction="left" height="80" :speed="50" :gap="80">
 *    <text>跑马灯文字内容</text>
 *  </wht-race-lamp>
 -->

<template>
  <view class="wht-race-lamp" :style="containerStyle">
    <view class="wht-race-lamp__wrapper" :class="[direction]" :style="wrapperStyle" @touchstart="onTouchStart"
      @touchend="onTouchEnd">
      <view class="wht-race-lamp__content" ref="contentRef">
        <slot></slot>
      </view>
      <view class="wht-race-lamp__content">
        <slot></slot>
      </view>
      <view class="wht-race-lamp__content">
        <slot></slot>
      </view>
      <view class="wht-race-lamp__content">
        <slot></slot>
      </view>
      <view class="wht-race-lamp__content">
        <slot></slot>
      </view>
    </view>
  </view>
</template>

<script>
/**
 * wht-race-lamp 跑马灯组件
 * @description 支持水平和垂直方向的文字滚动效果
 */
export default {
  name: 'wht-race-lamp',
  props: {
    direction: {
      type: String,
      default: 'left',
      validator: (value) => ['left', 'right', 'up', 'down'].includes(value)
    },
    speed: {
      type: Number,
      default: 60
    },
    delay: {
      type: Number,
      default: 0
    },
    height: {
      type: [String, Number],
      default: 80
    },
    autoplay: {
      type: Boolean,
      default: true
    },
    gap: {
      type: [String, Number],
      default: 0
    }
  },
  data() {
    return {
      isRunning: false,
      offset: 0,
      contentSize: 0,
      containerSize: 0,
      animationId: null,
      lastTimestamp: 0
    }
  },
  computed: {
    containerStyle() {
      return {
        height: typeof this.height === 'number' ? this.height + 'rpx' : this.height
      }
    },
    wrapperStyle() {
      const transform = this.isVertical
        ? `translateY(${this.offset}px)`
        : `translateX(${this.offset}px)`

      return {
        transform,
        transition: this.isRunning ? 'none' : 'transform 0.3s'
      }
    },
    isVertical() {
      return ['up', 'down'].includes(this.direction)
    }
  },
  mounted() {
    this.$nextTick(() => {
      setTimeout(() => {
        this.initSize()
        if (this.autoplay) {
          setTimeout(() => {
            this.start()
          }, this.delay * 1000)
        }
      }, 100)
    })
  },
  beforeDestroy() {
    this.stop()
  },
  methods: {
    async initSize() {
      const query = uni.createSelectorQuery().in(this)
      query.select('.wht-race-lamp__content').boundingClientRect(data => {
        if (!data) return

        if (this.isVertical) {
          this.contentSize = data.height
          this.offset = this.direction === 'down' ? -this.contentSize * 2 : -this.contentSize
        } else {
          this.contentSize = data.width
          this.offset = this.direction === 'right' ? -this.contentSize * 2 : -this.contentSize
        }
      }).exec()
    },
    start() {
      if (this.isRunning) return
      this.isRunning = true
      this.lastTimestamp = Date.now()
      this.animate()
    },
    stop() {
      this.isRunning = false
      if (this.animationId) {
        clearTimeout(this.animationId)
        this.animationId = null
      }
    },
    animate() {
      if (!this.isRunning) return

      const now = Date.now()
      const deltaTime = now - this.lastTimestamp
      const step = (this.speed * deltaTime) / 1000

      let newOffset = this.offset

      if (['left', 'up'].includes(this.direction)) {
        newOffset -= step
        if (Math.abs(newOffset) >= this.contentSize * 3) {
          newOffset = -this.contentSize
        }
      } else {
        newOffset += step
        if (newOffset >= -this.contentSize) {
          newOffset = -this.contentSize * 3
        }
      }

      this.offset = newOffset
      this.lastTimestamp = now

      this.animationId = setTimeout(() => {
        this.animate()
      }, 16)
    },
    onTouchStart() {
      this.stop()
    },
    onTouchEnd() {
      if (this.autoplay) {
        this.start()
      }
    }
  }
}
</script>

<style lang="scss">
.wht-race-lamp {
  position: relative;
  width: 100%;
  overflow: hidden;
  height: 80rpx;

  &__wrapper {
    position: relative;
    height: 100%;
    will-change: transform;

    &.up,
    &.down {
      display: flex;
      flex-direction: column;

      align-items: center;
      height: 100%;
    }

    &.left,
    &.right {
      display: flex;
      flex-direction: row;
    }
  }

  &__content {
    flex-shrink: 0;
    height: 100%;
    display: flex;
    align-items: center;
    margin-right: v-bind('typeof gap === "number" ? gap + "rpx" : gap');

    &:last-child {
      margin-right: 0;
    }
  }
}
</style>